﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading;

namespace JiveMessenger.Log
{
    public class AsyncSynchronizationContext : SynchronizationContext
    {
        public static AsyncSynchronizationContext Register()
        {
            var syncContext = Current;
            if (syncContext == null)
                throw new InvalidOperationException("Ensure a synchronization context exists before calling this method.");

            var customSynchronizationContext = syncContext as AsyncSynchronizationContext;

            if (customSynchronizationContext == null)
            {
                customSynchronizationContext = new AsyncSynchronizationContext(syncContext);
                SetSynchronizationContext(customSynchronizationContext);
            }

            return customSynchronizationContext;
        }

        private readonly SynchronizationContext _syncContext;

        public AsyncSynchronizationContext(SynchronizationContext syncContext)
        {
            _syncContext = syncContext;
        }

        public override SynchronizationContext CreateCopy()
        {
            return new AsyncSynchronizationContext(_syncContext.CreateCopy());
        }

        public override void OperationCompleted()
        {
            _syncContext.OperationCompleted();
        }

        public override void OperationStarted()
        {
            _syncContext.OperationStarted();
        }

        public override void Post(SendOrPostCallback d, object state)
        {
            _syncContext.Post(WrapCallback(d), state);
        }

        public override void Send(SendOrPostCallback d, object state)
        {
            _syncContext.Send(d, state);
        }

        private static SendOrPostCallback WrapCallback(SendOrPostCallback sendOrPostCallback)
        {
            return state =>
            {
                Exception exception = null;

                try
                {
                    sendOrPostCallback(state);
                }
                catch (Exception ex)
                {
                    exception = ex;
                }

                if (exception != null)
                    ExceptionHandler.HandleException(exception);
            };
        }
    }
    public static class ExceptionHandler
    {

        public static void LogException(Exception ex)
        {
            Debug.WriteLine(ex.ToString());
            Logger.GetLogger().ErrorException(GetDisplayMessage(ex), ex);
            // e.g. MarkedUp.AnalyticClient.Error(ex.Message, ex);
        }

        /// <summary>
        /// Handles failure for application exception on UI thread (or initiated from UI thread via async void handler)
        /// </summary>
        public static void HandleException(Exception ex)
        {

            LogException(ex);

           
            //Execute.OnUIThread(async () =>
            //{
            //    var dialog = new MessageDialog(GetDisplayMessage(ex), "Unknown Error");
            //    await dialog.ShowAsync();
            //});

        }

        /// <summary>
        /// Gets the error message to display from an exception
        /// </summary>
        public static string GetDisplayMessage(Exception ex)
        {
            string errorMessage;
#if DEBUG
            errorMessage = (ex.Message + " " + ex.StackTrace);
#else
                errorMessage = "An unknown error has occurred, please try again";
#endif
            return errorMessage;
        }

    }
}
